<?php

namespace App\Http\Middleware;

use App\Exceptions\LoginException;
use App\Exceptions\SuperAdminException;
use App\Helpers\MvcHelper;
use App\Services\Admin\SuperAdmin\User\UserService;
use Closure;
use Exception;
use Illuminate\Http\Request;

class AdminAuthMiddleware
{
    /**
     * @throws LoginException
     * @throws Exception
     */
    public function handle(Request $request, Closure $next)
    {
        $request->merge(['custom_param' => 'value_from_middleware']);
        $token = MvcHelper::getLoginToken();
        // 判断 token 是否有效
        $userInfo = verifyJwt($token);
        // 检测用户是否存在
        $userData = $this->getUserService()->getCheckUserInfo($userInfo['userId']);
        if (empty($userData)) {
            throw new LoginException('登录状态失效，请重新登录', LoginException::CODE_1000);
        }
        // 暂存token过期时间(为了全局获取，退出登录时加入jwt黑名单用)
        MvcHelper::makeLoginTokenExpire($userInfo['exp']);

        // 检测用户是否禁用
        if ($this->getUserService()->checkForbidden($userData['enable'])) {
            throw new LoginException('非法用户，请联系客服检查用户状态', LoginException::CODE_1003);
        }

        // 接口路径
        $path = $request->decodedPath();

        // 检查接口权限
        if (!$this->checkApiAuth($userData['id'], $userData['authority_id'], $path)) {
            throw new SuperAdminException("没有接口权限", SuperAdminException::CODE_2000);
        }

        // 设置用户缓存
        MvcHelper::setUserInfCache($userData);

        return $next($request);
    }

    /**
     * @return UserService
     * @throws Exception
     */
    private function getUserService(): UserService
    {
        return loadService('Admin\SuperAdmin\User\UserService');
    }

    /**
     * @throws Exception
     */
    private function checkApiAuth(int $userId, int $authorityId, string $path): bool
    {
        // @tips 用户权限白名单 << 超级管理员 >>
        $apiUserIds = [
            1,
        ];
        if (in_array($userId, $apiUserIds)) {
            return true;
        }

        $apis = $this->getUserService()->getApisPathByAuthorityId($authorityId);
        if (empty($apis)) {
            return false;
        }
        // 加工api前缀(此处做逻辑替换)数据库的api不感知api前缀
        $baseApi = MvcHelper::getBaseApi();
        $baseApiLen = strlen($baseApi);
        if ($baseApiLen > 0) {
            $idx = stripos($path, MvcHelper::getBaseApi());
            if ($idx !== false) {
                // 替换前缀
                $path = substr_replace($path, "", $idx, $baseApiLen);
            }
        }

        return in_array(DIRECTORY_SEPARATOR . $path, $apis);
    }

}
